package com.shelpe.services.sinbadgateway.controller;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.shelpe.services.sinbadgateway.client.LexiconClient;
import com.shelpe.services.sinbadgateway.client.LexiconClient.RecommendWordDto;
import com.shelpe.services.sinbadgateway.client.SinbadClient;
import com.shelpe.services.sinbadgateway.client.SinbadClient.Keyword;
import com.shelpe.services.sinbadgateway.client.SinbadClient.ListResponse;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;

@Controller
@RequestMapping("/sinbadgateway/users/{user_id}")
@Slf4j
public class WordController {

	@Autowired
	private LexiconClient lexiconClient;
	@Autowired
	private SinbadClient sinbadClient;

	@RequestMapping(path = "/adgroups/{adgroup_id}/@autoWords", method = RequestMethod.GET)
	@ResponseBody
	public AutoWordsDto autoWords(@PathVariable("user_id") long userID, @PathVariable("adgroup_id") long adgroupID,
			@RequestParam(value = "device", defaultValue = "0") int device) {
		AutoWordsDto dto = new AutoWordsDto();

		List<RecommendWordDto> recommends = this.lexiconClient.smartWordsAsDevice(adgroupID, device);
		if (recommends != null && recommends.size() > 0) {
			ListResponse<Keyword> keywords = this.sinbadClient.findKeyworsdByAdgroupID(adgroupID);
			
			if(keywords == null || keywords.getDatas() == null){
				log.info("not find keywords: userID - {}, adgroupID- {}", userID, adgroupID);
				dto.setKeywords(new ArrayList<AutoWordDto>());
				return dto;
			}

			RecommendWordDto max = new RecommendWordDto();
			for (RecommendWordDto recommend : recommends) {
				if (recommend.getClick() > max.getClick()) {
					max.setClick(recommend.getClick());
				}
				if (recommend.getPageVolume() > max.getPageVolume()) {
					max.setPageVolume(recommend.getPageVolume());
				}
				if (recommend.getPertinence() > max.getPertinence()) {
					max.setPertinence(recommend.getPertinence());
				}
				if (recommend.getClickRatio() > max.getClickRatio()) {
					max.setClickRatio(recommend.getClickRatio());
				}
				if (recommend.getImpression() > max.getCompetition()) {
					max.setImpression(recommend.getImpression());
				}
			}

			max.setImpression(Math.max(max.getImpression(), 1));
			max.setClickRatio(Math.max(max.getClickRatio(), 0.01f));
			max.setPertinence(Math.max(max.getPertinence(), 1));
			for (RecommendWordDto recommend : recommends) {
				if (!this.exist(keywords.getDatas(), recommend.getWord()) && recommend.isCenteral()) {
					log.debug("recommend will to add:{}", recommend);
					AutoWordDto wordDto = new AutoWordDto();
					BeanUtils.copyProperties(recommend, wordDto);
					float score = (((float) recommend.getImpression()) / max.getImpression()) * 35;
					score = score + (((float) recommend.getClickRatio()) / max.getClickRatio()) * 60;
					score = score + (((float) recommend.getPertinence()) / max.getPertinence()) * 5;
					wordDto.setScore((int) score);
					dto.addKeyword(wordDto);
				}
			}

			Collections.sort(dto.getKeywords(), new Comparator<AutoWordDto>() {
				@Override
				public int compare(AutoWordDto o1, AutoWordDto o2) {
					return o2.getScore() - o1.getScore();
				}
			});
			for (AutoWordDto word : dto.getKeywords()) {
				if (word.getPrice() == 0) {
					word.setPrice(0.05f);
				}
			}
			if (dto.getKeywords() != null && dto.getKeywords().size() > 20) {
				dto.setKeywords(dto.getKeywords().subList(0, 20));
			}

		} else {
			log.warn("not find recommends: userID - {}, adgroupID- {}", userID, adgroupID);
		}

		return dto;
	}

	private boolean exist(List<Keyword> keywords, String word) {
		boolean exist = false;
		for (Keyword keyword : keywords) {
			if (word.equals(keyword.getWord())) {
				exist = true;
				break;
			}
		}
		return exist;
	}

	@Data
	public static class AutoWordsDto {

		private List<AutoWordDto> keywords;

		public void addKeyword(AutoWordDto dto) {
			if (this.keywords == null) {
				this.keywords = new ArrayList<AutoWordDto>();
			}
			this.keywords.add(dto);
		}
	}

	@Data
	public static class AutoWordDto {
		private String word;
		@JsonProperty("max_price")
		private float price;
		@JsonProperty("match_scope")
		private int matchScope = 4;

		@JsonIgnore
		private int score;
	}
}
